#ifndef CREASESTRUCTURE_HPP
#define CREASESTRUCTURE_HPP
#include "GeometryTypes.hpp"

struct RegionCrease;

struct VertexLoop
{
   void RecomputeHash()
   {
      mHashValue = 0;
      for (size_t i = 0; i < mVertices.size(); ++i)
      {
         mHashValue += mVertices[i];
      }
   }
   typedef boost::tuple<int,int,int> ID;
   ID GetId() const { return ID(mHashValue, mVertices.size(), mVertices.front()); }
   bool operator==(const VertexLoop& aRhs) const
   {
      return GetId() == aRhs.GetId();
   }
   bool operator<(const VertexLoop& aRhs) const
   {
      return GetId() < aRhs.GetId();
   }
   void Normalize();
   //bool IsLoopEqual(VertexLoop& a,
      //VertexLoop& b);
   void RemoveRegion(RegionCrease* c)
   {
      mCreases.erase(std::find(mCreases.begin(), mCreases.end(), c));
   }
   int         mHashValue;
   IndexList   mVertices;  
   std::vector<RegionCrease*> mCreases;
};

struct RegionCrease
{
   void RemoveLoop(VertexLoop* c)
   {
      mLoops.erase(std::find(mLoops.begin(), mLoops.end(), c));
   }

   RegionInterface          mInterface;
   std::vector<int>         mFaces;
   std::vector<VertexLoop*> mLoops;
};
// maintains data about a mesh's crease structure.
// the basic idea here is to identify surface patches with the same material information
// and the loops of vertices that surround them
// creases are drawn using this information
// used to removing unwanted interfaces
class CreaseStructure
{
   public:
      CreaseStructure();
      ~CreaseStructure();
      void Build(const FaceList& aFaces);
      void Rebuild(const FaceList&   aFaces,
                   std::vector<int>& aScrapRegions,
                   std::vector<int>& aScrapLoops);
      void AddPatch(RegionCrease* aPatch) { mPatches.push_back(aPatch); }
      void AddLoop(VertexLoop* aLoop) { mLoops.push_back(aLoop); }
      void Clear()
      {
         for (size_t i = 0; i < mPatches.size(); ++i)
         {
            delete mPatches[i];
         }
         for (size_t i = 0; i < mLoops.size(); ++i)
         {
            delete mLoops[i];
         }
         mPatches.clear();
         mLoops.clear();
      }
      VertexLoop* Add(VertexLoop* aLoopPtr)
      {
         for (size_t i = 0; i < mLoops.size(); ++i)
         {
            if (*mLoops[i] == *aLoopPtr)
            {
               delete aLoopPtr;
               return mLoops[i];
            }
         }
         mLoops.push_back(aLoopPtr);
         return aLoopPtr;
      }
      int FindLoop(VertexLoop::ID aId) const
      {
         for (size_t i = 0; i < mLoops.size(); ++i)
         {
            if (mLoops[i]->GetId() == aId) return i;
         }
         return -1;
      }
      int CreaseIndex(RegionCrease* aCrease)
      {
         for (size_t ind = 0; ind < mPatches.size(); ++ind) { if (mPatches[ind] == aCrease) return ind; }
         return -1;
      }
      int LoopIndex(VertexLoop* aLoop)
      {
         for (size_t ind = 0; ind < mLoops.size(); ++ind) { if (mLoops[ind] == aLoop) return ind; }
         return -1;
      }
      std::vector<RegionCrease*> mPatches;
      std::vector<VertexLoop*>   mLoops;
      
};

#endif
